package com.mxchip.livestarmobile.mobile.ui.call

import android.app.Application
import android.os.Looper
import android.util.Log
import androidx.lifecycle.*
import com.mxchip.livestarmobile.mobile.av.screen.DecoderScreen
import com.mxchip.livestarmobile.mobile.av.screen.PreviewScreen
import com.mxchip.livestarmobile.mobile.av.screen.Screen
import com.mxchip.livestarmobile.mobile.av.screen.ScreenSettings
import com.mxchip.livestarmobile.mobile.state.SystemData
import com.mxchip.livestarmobile.mobile.util.Camera.CameraHandle
import com.mxchip.livestarmobile.mobile.util.Log.MyLog
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class ScreenViewModel(application: Application) : AndroidViewModel(application) {
    private val mIsEnter = MutableLiveData<Boolean>(false)
    private val mScreenSettings = MediatorLiveData<ScreenSettings>()
    private val mRefreshMainStream = MediatorLiveData<Boolean>()
    val screenSettings: LiveData<ScreenSettings>
        get() = mScreenSettings

    val avDevices = MutableLiveData<List<AVDevice>>(arrayListOf())
    private val _networkLevel = MutableLiveData(0)


    val networkLevel: LiveData<Int>
        get() = _networkLevel

    private val timer = MutableLiveData<Long>(System.currentTimeMillis())
    private val needLayout = MutableLiveData<Boolean>(false)
    private val manualSelection = MutableLiveData(1)

    private var isMainScreenMode = false

    private var isFrontCameraPreviewEnable = false
    private var isHDMICameraPreviewEnable = false
    private var isWifiCameraPreviewEnable = false

    private var currentPage = 1
    fun setAVDevices(devices: List<AVDevice>) {
        Log.d(TAG, "setAVDevices: $devices")
        avDevices.postValue(devices)
    }

    private var selectedScreen: Screen? = null
    private val screenSettingsObserver = Observer<Any> { data ->
        if (mIsEnter.value != null
                && mIsEnter.value == false) {
            return@Observer
        }
//        Log.e("ScreenViewModel", "screenSettingsObserver $data")

        val devices = avDevices.value?.toList()

        Log.e("ScreenViewModel", "avDevices $devices isFrontCameraPreviewStart $isFrontCameraPreviewEnable is CameraOpen ${CameraHandle.getInstance().isCameraOpen} ")

        val screenSettings = ScreenSettings(application.applicationContext)


        val hdmiCameraDevices = devices?.filter {
            it.deviceName == AVDevice.CAMERA_HDMI
        }

        val wifiCameraDevices = devices?.filter {
            it.deviceName == AVDevice.CAMERA_WIFI
        }

        val frontCameraSmallDevices = devices?.filter {
            it.deviceName == AVDevice.CAMERA_LOCAL_SMALL
        }?.toMutableList()

        val frontCameraDevices = devices?.filter {
            it.deviceName == AVDevice.CAMERA_LOCAL
        }?.toMutableList()


//        Log.e("ScreenViewModel", "frontCameraSmallDevices $frontCameraSmallDevices \nfrontCameraDevices $frontCameraDevices \nhdmiCameraDevices $hdmiCameraDevices \nwifiCameraDevices $wifiCameraDevices")


        if (selectedScreen != null && selectedScreen is DecoderScreen) {
            val decoderScreen = selectedScreen as DecoderScreen

            if (devices == null || devices.none { it.uid == decoderScreen.deviceUid && it.deviceName == decoderScreen.deviceName }) {
                selectedScreen = null
            }
        }

        screenSettings.mainScreen = when {
            isHDMICameraPreviewEnable -> {
                PreviewScreen(PreviewScreen.Type.HDMICamera)
            }
            isWifiCameraPreviewEnable -> {
                PreviewScreen(PreviewScreen.Type.WIFICamera)
            }
            !hdmiCameraDevices.isNullOrEmpty() -> {
                DecoderScreen(hdmiCameraDevices[0])
            }
            !wifiCameraDevices.isNullOrEmpty() -> {
                DecoderScreen(wifiCameraDevices[0])
            }
            !frontCameraSmallDevices.isNullOrEmpty() -> {

                var screen: DecoderScreen? = null

                if (selectedScreen == null) {

                    val frontCameraSmallDevice = frontCameraSmallDevices.removeAt(0)

                    val device = if (networkLevel.value!! > SystemData.networkLevelLower) {
                        frontCameraSmallDevice
                    } else {
                        frontCameraDevices?.firstOrNull { it.uid == frontCameraSmallDevice.uid }
                                ?: frontCameraSmallDevice
                    }

//                    Log.e("ScreenViewModel", "selectedScreen == null $device")

                    screen = DecoderScreen(device)
                }

                if (selectedScreen != null && selectedScreen is DecoderScreen) {
                    val decoderScreen = selectedScreen as DecoderScreen

                    val frontCameraSmallDevice = frontCameraSmallDevices.firstOrNull { it.deviceName == decoderScreen.deviceName && it.uid == decoderScreen.deviceUid }

                    frontCameraSmallDevice?.let {
                        frontCameraSmallDevices.remove(it)
                    }

                    val device = frontCameraDevices?.firstOrNull { it.uid == decoderScreen.deviceUid }
                            ?: frontCameraSmallDevice
//                    Log.e("ScreenViewModel", "selectedScreen != null $device")
                    device?.let {
                        screen = DecoderScreen(it)
                    }
                }

                screen
            }
            isFrontCameraPreviewEnable -> {
                PreviewScreen(PreviewScreen.Type.FrontCamera)
            }
            else -> {
                null
            }
        }

        // 隐藏右侧4个小窗口
        if (isMainScreenMode) {
            mScreenSettings.value = screenSettings
            return@Observer
        }

        if (screenSettings.mainScreen != null && screenSettings.mainScreen != PreviewScreen(PreviewScreen.Type.FrontCamera)) {
            when {
                isFrontCameraPreviewEnable -> {
                    screenSettings.setSideScreens(PreviewScreen(PreviewScreen.Type.FrontCamera), 0)
                }
            }
        }

        val pageSize = screenSettings.sideScreens.filter { it == null }.size
        val totalSize = frontCameraSmallDevices?.size ?: 0

        if (pageSize > 0 && totalSize > 0) {

            val totalPage = if (totalSize % pageSize == 0) {
                totalSize / pageSize
            } else {
                totalSize / pageSize + 1
            }
            currentPage = manualSelection.value!!
            if (currentPage > totalPage) {
                currentPage = totalPage
            }

            // 定时器触发分页增加
            if (data is Long) {
                if (++currentPage > totalPage) {
                    currentPage = 1
                }
            }
            val indexes = arrayOfNulls<Int>(pageSize)

            val startIndex = (currentPage - 1) * pageSize

            // 最后一页如果不足pageSize大小补齐
            if (currentPage == totalPage && currentPage > 1 && totalSize % pageSize != 0) {

                val preIndex = startIndex - pageSize

                for (i in indexes.indices) {
                    indexes[i] = preIndex + i
                }

                for (i in 0 until totalSize - startIndex) {
                    indexes[i] = startIndex + i
                }

                // startIndex = totalSize - pageSize
            } else {
                for (i in indexes.indices) {
                    indexes[i] = startIndex + i
                }
            }

            Log.e("ScreenViewModel", "indexes: $indexes")

            val indexList = indexes.toMutableList()

            screenSettings.sideScreens.forEachIndexed { i, screen ->
                if (screen == null && startIndex < totalSize) {

                    val index = indexList.removeAt(0)

                    if (index != null && index < totalSize) {
                        val avDevice = frontCameraSmallDevices?.get(index)

                        if (avDevice != null) {
                            screenSettings.setSideScreens(DecoderScreen(avDevice), i)
//                            Log.e("ScreenViewModel", "setSideScreens: $avDevice $i")
                        }
                    }
                }
            }
        }

        Log.e("ScreenViewModel", "screenSettings $screenSettings")

        mScreenSettings.value = screenSettings
    }

    var lastModify = 0L
    private var smallDeviceMainStream = false
    private val check = MutableLiveData<Boolean>(false)
    private val refreshMainObserver = Observer<Any> { data ->
        if (!smallDeviceMainStream && networkLevel.value!! > SystemData.networkLevelLower) {
            Log.d("ScreenViewModel", "refreshMainObserver:$smallDeviceMainStream ")
            lastModify = System.currentTimeMillis()
            smallDeviceMainStream = true
            changeNeedLayout(true)
        }

        if (smallDeviceMainStream
                && networkLevel.value!! <= SystemData.networkLevelLower
                && (System.currentTimeMillis() - lastModify) / 1000 > 10) {
            Log.d("ScreenViewModel", "refreshMainObserver:$smallDeviceMainStream ")
            smallDeviceMainStream = false
            changeNeedLayout(true)
        }


    }

    private fun changeNeedLayout(b:Boolean) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            needLayout.value = b
        } else {
            needLayout.postValue(b)
        }
    }

    private val TAG = "ScreenViewModel"
    fun frontCameraPreview(start: Boolean) {

//        Log.e("ScreenViewModel", "frontCameraPreview isFrontCameraPreviewStart $isFrontCameraPreviewEnable")
        Log.d(TAG, "frontCameraPreview: ")
        isFrontCameraPreviewEnable = start

        needLayout.value = true
    }


    fun setSelectSomeOne(index: Int) {
        val screen = screenSettings.value?.sideScreens?.get(index - 1)
        selectedScreen = screen
        needLayout.value = true
    }


    fun manualSelection(next: Boolean) {
        if (next) {
            manualSelection.value = currentPage + 1
        } else {
            manualSelection.value = if (currentPage - 1 < 1) 1 else {
                currentPage - 1
            }
        }
        MyLog.logD(MyLog.SCREEN_VIEW_MODEL_MODEL, "ScreenViewModel::manualSelection: mScreenSettings.value:${mScreenSettings.value}  currentPage:$currentPage")
    }

    fun mainScreenMode(): Boolean {
        return isMainScreenMode
    }

    fun mainScreenMode(v: Boolean) {
        this.isMainScreenMode = v
        needLayout.value = true
    }

    init {
        mScreenSettings.addSource(avDevices, screenSettingsObserver)
//        mScreenSettings.addSource(timer, screenSettingsObserver)
        mScreenSettings.addSource(needLayout, screenSettingsObserver)
        mScreenSettings.addSource(manualSelection, screenSettingsObserver)

        mRefreshMainStream.addSource(networkLevel, refreshMainObserver)
        mRefreshMainStream.addSource(check, refreshMainObserver)

        viewModelScope.launch {
            while (true) {
                delay(10 * 1000)
                timer.value = System.currentTimeMillis()
            }
        }

    }

    private val avRepository = ScreenRepository

    val streamingAVDevices: LiveData<Set<AVDevice>>
        get() = avRepository.streamingAVDevices

    fun addStreamingAVDevice(device: AVDevice) {
        avRepository.addStreamingAVDevice(device)
    }

    fun removeStreamingAVDevice(uid: String, deviceName: String) {
        avRepository.removeStreamingAVDevice(uid, deviceName)
    }

    fun enterAfterJoined() {
        mIsEnter.value = true
    }


    fun networkLevel(networkLevel: Int) {

        if (networkLevel != this.networkLevel.value!!) {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                _networkLevel.value = networkLevel
            } else {
                _networkLevel.postValue(networkLevel)
            }
        } else {
            if (Looper.myLooper() == Looper.getMainLooper()) {
                check.value = true
            } else {
                check.postValue(true)
            }
        }
    }

}